// 算法测试
import { PrismaClient } from "@prisma/client";
import Router from "koa-router";
import path from "path";
import { spawn, spawnSync } from "child_process";
import { PassThrough } from "stream";
import { deleteFolderRecursive } from "./dataset";

const prisma = new PrismaClient();

const testRouter = new Router();

testRouter.prefix("/test");

testRouter.get("/run/:id", async (ctx) => {
  const { id } = ctx.params;
  const dataset = await prisma.dataset.findUnique({
    include: { testResult: true },
    where: {
      id: Number(id),
    },
  });
  const inputPath = path.join(
    process.cwd(),
    "app",
    "dataset",
    dataset.name,
    "images"
  );
  const appPath = path.join(process.cwd(), "app");

  deleteFolderRecursive(path.join(appPath, "output"));

  const child = spawn(
    "python",
    [
      "my_detect.py",
      "--source",
      inputPath,
      "--project",
      appPath,
      "--name",
      "output",
      "--save-txt",
      "--save-conf",
      "--exist-ok",
    ],
    { cwd: path.join(process.cwd(), "app", "yolov5") }
  );

  ctx.request.socket.setTimeout(0);
  ctx.req.socket.setNoDelay(true);
  ctx.req.socket.setKeepAlive(true);
  ctx.set("Content-Type", "text/event-stream;charset=utf-8");
  ctx.set("Cache-Control", "no-cache");
  ctx.set("Connection", "keep-alive");
  ctx.status = 200;
  const stream = new PassThrough();
  ctx.body = stream;

  child.stdout.on("data", (data) => {
    const buffer = Buffer.from(data);
    const text = buffer.toString("utf-8");
    if (text.startsWith("image")) {
      const strs = text.split(" ");
      const percent = Math.round(
        (Number(strs[1].split("/")[0]) / Number(strs[1].split("/")[1])) * 100
      );
      stream.write(`data: ${percent}\n\n`);
    }
  });

  child.on("close", async () => {
    ctx.set("Content-Type", "text/event-stream;charset=utf-8");
    ctx.set("Cache-Control", "no-cache");
    ctx.set("Connection", "keep-alive");

    const child = spawnSync(
      "python",
      [
        "print_mAP_50_95_value.py",
        "--folderDet",
        path.join(process.cwd(), "app", "output", "labels"),
        "--folderGT",
        path.join(process.cwd(), "app", "dataset", dataset.name, "labels"),
      ],
      { cwd: path.join(process.cwd(), "app", "mAP") }
    );

    const [indicator1, indicator2] = child.stdout
      .toString("utf-8")
      .trim()
      .split(/[\n]/)
      .at(-1)
      .split(" ")
      .map((x) => parseFloat(x));

    if (dataset.testResult === null) {
      await prisma.testResult.create({
        data: {
          datasetId: dataset.id,
          indicator1,
          indicator2,
        },
      });
    } else {
      await prisma.testResult.update({
        where: { id: dataset.testResult.id },
        data: {
          indicator1,
          indicator2,
        },
      });
    }
    stream.write(`event: result\ndata: ${indicator1} ${indicator2} \n\n`);
  });
});

testRouter.get("/result", async (ctx) => {
  const { standard } = ctx.query;
  const results = await prisma.testResult.findMany({
    include: { dataset: true },
    where: { dataset: { standard: standard === "true" } },
    orderBy: { dataset: { noise: "asc" } },
  });
  ctx.body = {
    results,
  };
});

export default testRouter;
